////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_FIBERS_FIBER_MANAGER_IMPL_H__
#define __WN_FIBERS_FIBER_MANAGER_IMPL_H__

#include "WNCore/inc/WNPlatform.h"
#include "WNCore/inc/WNTypes.h"
#include "WNFibers/inc/WNFibers.h"
#include "WNConcurrency/inc/WNRecursiveMutex.h"

#ifdef _WN_MSVC
    #pragma warning(push)
    #pragma warning(disable: 4275)  // non - DLL-interface used as base for DLL-interface
#endif

#include <vector>
#include <deque>

#ifdef _WN_MSVC
    #pragma warning(pop)
#endif

namespace WNFibers {
    class WNFiberManager;
    struct WNFiberPrivateData;

    class WNFiberManagerImpl : public WNFiberManager {
    public:
        WNFiberManagerImpl();
        virtual ~WNFiberManagerImpl();

        virtual WN_BOOL Initialize(WN_UINT32 _maxStacks, WN_BOOL _updateOnDemand, WN_TICK_COUNT_FUNCTION_T _timeFunction = WN_NULL);
        virtual WNFiberData* CreateFiber(WN_FIBER_FUNCTION_T _function, WN_POINTER _startValue, WN_UINT32 _stackSize, WN_POINTER _userData = WN_NULL);
        virtual WNFiberData* GetNextStack();
        virtual WN_BOOL QueuedThreads();
        virtual WN_BOOL UpdateQueues(WN_UINT32 _time);
        virtual WN_VOID RunNextStack(WN_BOOL _continuous);

        WN_UINT32 GetTime();

    private:
        WNFiberData* CreateFiberData(WN_FIBER_FUNCTION_T _function, WN_POINTER startval, WN_UINT32 stacksize);
        WN_VOID DestroyFiberData(WNFiberData* s);
        WN_VOID ContinueOther(WNFiberData* s);

        WN_ATOM_T mThreadUpdating;
        WN_ATOM_T mDoneSpin;

        WNConcurrency::WNRecursiveMutex mThreadsLock;
        WNConcurrency::WNRecursiveMutex mDoneLock;
        WNConcurrency::WNRecursiveMutex mRunnableLock;

        std::vector<WNFiberData*> mThreads;
        std::vector<WNFiberData*> mDoneThreads;
        std::deque<WNFiberData*> mRunnableThreads;

        WN_UINT32 mMaxStacks;
        WN_BOOL mUpdateQueuesOnDemand;
        WN_UINT32 mNumActive;
        WN_TICK_COUNT_FUNCTION_T mTimeFunction;
    };
}

#endif // __WN_FIBERS_FIBER_MANAGER_IMPL_H__
